package com.hj.biz;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.ui.Model;
import org.springframework.web.multipart.MultipartFile;

import com.hj.biz.dao.SysFileDetailDao;
import com.hj.biz.dao.entity.SysFileDetail;
import com.hj.config.ConfigConstants;
import com.hj.exception.ServiceException;
import com.hj.model.FileAttribute;
import com.hj.model.FileType;
import com.hj.model.ReturnResponse;
import com.hj.service.FilePreview;
import com.hj.service.FilePreviewFactory;
import com.hj.service.fileserver.FileServer;
import com.hj.service.fileserver.FileServerFactory;
import com.hj.util.DownloadUtils;
import com.hj.util.FileUniqueIdUtils;
import com.hj.util.FileUtils;
import com.hj.util.SequenceWorker;

/**
 * @author dehui dou
 * @date 2020/9/23 16:50
 * @description 文件业务处理biz
 */
@Service
public class SysFileBiz {
    private static Logger logger = LoggerFactory.getLogger(SysFileBiz.class);

    @Autowired
    private SysFileDetailDao sysFileDetailDao;
    @Autowired
    private SequenceWorker sequenceWorker;
    @Autowired
    private DownloadUtils downloadUtils;
    @Autowired
    private AsyncTaskBiz asyncTaskBiz;

    /**
     * @author dehui dou
     * @description 文件上传
     * @param file
     * @param systemCode
     * @param shareSystemCode
     * @param filePath
     * @return java.lang.String
     */
    public String upload(MultipartFile file, String systemCode, String shareSystemCode, String filePath) {
        String originalFilename = file.getOriginalFilename();
        String fileUniqueId = FileUniqueIdUtils.getFileUniqueId(originalFilename);
        String extension = StringUtils.lowerCase(FilenameUtils.getExtension(originalFilename));
        try {
            byte[] fileData = file.getBytes();
            FileServer fileServer = FileServerFactory.get();
            // 上传
            String filefdfsid = fileServer.upload(file, extension, null);
            // 持久化db
            SysFileDetail sysFileDetail = new SysFileDetail();
            sysFileDetail.setId(sequenceWorker.nextId());
            sysFileDetail.setSystemCode(systemCode);
            sysFileDetail.setFilePath(StringUtils.isNotBlank(filePath) ? filePath : "/");
            sysFileDetail.setFileName(originalFilename);
            sysFileDetail.setFormat(extension);
            sysFileDetail.setFileSize("" + fileData.length);
            sysFileDetail.setFileUniqueId(fileUniqueId);
            sysFileDetail.setFileFdfsId(filefdfsid);
            sysFileDetail.setCreateTime(new Date());
            sysFileDetail.setUpdateTime(new Date());
            sysFileDetailDao.save(sysFileDetail);
        } catch (Exception e) {
            logger.error("文件上传失败", e);
            throw new ServiceException("系统错误,请联系管理员");
        }
        return fileUniqueId;
    }

    /**
     * @author dehui dou
     * @description 文件下载
     * @param fileUniqueId
     * @param response
     * @return void
     */
    public void download(String fileUniqueId, HttpServletResponse response) {
        SysFileDetail sysFileDetail = sysFileDetailDao.getOneByUniqueId(fileUniqueId);
        if (sysFileDetail == null) {
            logger.warn("文件下载失败,文件不存在");
            throw new ServiceException("文件下载失败,文件不存在");
        }
        String fileName = sysFileDetail.getFileName();
        FileServer fileServer = FileServerFactory.get();
        byte[] fileData = fileServer.download(sysFileDetail.getFileFdfsId());
        if (fileData == null || fileData.length == 0) {
            logger.warn("文件下载失败,获取文件为空");
            throw new ServiceException("文件下载失败,获取文件为空");
        }
        try {
            OutputStream out = response.getOutputStream();
            response.setContentType("application/octet-stream;charset=utf-8");
            response.addHeader("Content-Disposition", "attachment;filename=" +
                    new String(sysFileDetail.getFileName().getBytes("utf-8"), "ISO8859-1"));
            response.addHeader("Content-Length", fileData.length + "");
            out.write(fileData);
            out.close();
        } catch (IOException e) {
            logger.error("文件下载失败", e);
            throw new ServiceException("系统错误,请联系管理员");
        }
    }

    /**
     * @author dehui dou
     * @description 图片展示
     * @param fileUniqueId
     * @param response
     * @return void
     */
    public void img(String fileUniqueId, HttpServletResponse response) {
//        Date date = new Date();
//        // 设置协商缓存
//        try {
//            HttpServletRequest request =
//                    ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
//            String lastUpdateTime = request.getHeader("if-modified-since");
//            if (lastUpdateTime != null && !"".equals(lastUpdateTime)) {
//                long d = Date.parse(lastUpdateTime);
//                d = d + 60 * 1000 * 2;
//                Date ifModifiedSince = new Date(d);
//                if (ifModifiedSince.compareTo(date) >= 0) {
//                    // 2分钟之内，都返回304，让浏览器取缓存数据
//                    response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
//                    return;
//                }
//            }
//        } catch (Exception e) {
//        }
//        // 设置缓存为私有缓存，不在用户之间共享
//        response.setHeader("Cache-Control", "private");
//        // 浏览器在response中发现该字段，才会将数据存入缓存中，（标记最后修改时间）
//        response.setDateHeader("Last-Modified", date.getTime());

        SysFileDetail sysFileDetail = sysFileDetailDao.getOneByUniqueId(fileUniqueId);
        if (sysFileDetail == null) {
            logger.warn("文件下载失败,文件不存在");
            throw new ServiceException("文件下载失败,文件不存在");
        }
        FileServer fileServer = FileServerFactory.get();
        byte[] fileData = fileServer.download(sysFileDetail.getFileFdfsId());
        if (fileData == null || fileData.length == 0) {
            logger.warn("文件下载失败,获取文件为空");
            throw new ServiceException("文件下载失败,获取文件为空");
        }
        try {
            OutputStream out = response.getOutputStream();
            response.setContentType("image/png;charset=UTF-8");
            out.write(fileData);
            out.close();
        } catch (IOException e) {
            logger.error("图片文件下载失败", e);
            throw new ServiceException("系统错误,请联系管理员");
        }
    }

    /**
     * @author dehui dou
     * @description 文件预览
     * @param model
     * @param fileAttribute
     * @return java.lang.String
     */
    public String view(Model model, FileAttribute fileAttribute) throws Exception {
        if (StringUtils.isNotEmpty(fileAttribute.getUrl())) {
            return UrlView(model, fileAttribute);
        }
        if (StringUtils.isNotEmpty(fileAttribute.getFileKey())
                && StringUtils.isNotEmpty(fileAttribute.getFileUniqueId())) {
            return fileKeyView(model, fileAttribute);
        }
        if (StringUtils.isNotEmpty(fileAttribute.getFileUniqueId())) {
            return CommonView(model, fileAttribute);
        }
        model.addAttribute("msg", "请求参数错误,请确认参数");
        return "fileNotSupported";
    }

    /**
     * @author dehui dou
     * @description 普通预览:fileUniqueId
     * @param model
     * @param fileAttribute
     * @return java.lang.String
     */
    private String CommonView(Model model, FileAttribute fileAttribute) {
        String fileUniqueId = fileAttribute.getFileUniqueId();
        String extension, fileName, filePath;
        SysFileDetail sysFileDetail = sysFileDetailDao.getOneByUniqueId(fileUniqueId);
        if (sysFileDetail == null) {
            model.addAttribute("msg", "文件不存在");
            return "fileNotSupported";
        }
        FileType fileType = FileUtils.typeFromFileFormat(sysFileDetail.getFormat());
        FilePreview filePreview = FilePreviewFactory.get(fileType);
        if (filePreview == null) {
            model.addAttribute("msg", String.format("文件类型【%s】不支持", fileType));
            return "fileNotSupported";
        }

        extension = sysFileDetail.getFormat();
        fileName = String.format("%s.%s", fileUniqueId, extension);
        filePath = String.format(ConfigConstants.getFileDir() + File.separator + fileName);
        File file = new File(filePath);
        if (!file.exists()) {
            FileServer fileServer = FileServerFactory.get();
            byte[] fileData = fileServer.download(sysFileDetail.getFileFdfsId());
            if (fileData == null || fileData.length == 0) {
                logger.warn("文件下载失败,获取文件为空");
                model.addAttribute("msg", "文件不存在");
                return "fileNotSupported";
            }
            FileUtils.saveBytesToFile(fileData, file);
        }
        fileAttribute.setFileRealName(sysFileDetail.getFileName());
        fileAttribute.setFileViewName(fileName);
        return filePreview.filePreviewHandle(model, fileAttribute);
    }

    /**
     * @author dehui dou
     * @description url参数方式预览, 参数:url
     * @param model
     * @param fileAttribute
     * @return java.lang.String
     */
    private String UrlView(Model model, FileAttribute fileAttribute) throws Exception {
        String url = fileAttribute.getUrl();
        fileAttribute = FileUtils.getFileAttribute(url);
        String suffix = fileAttribute.getSuffix();
        FileType fileType = FileUtils.typeFromFileFormat(suffix);
        FilePreview filePreview = FilePreviewFactory.get(fileType);
        if (filePreview == null) {
            model.addAttribute("msg", String.format("文件类型【%s】不支持", fileType));
            return "fileNotSupported";
        }
        String fileViewName = FileUniqueIdUtils.getFileUniqueId(fileAttribute.getName()) + "." + suffix;
        ReturnResponse<String> response = downloadUtils.downLoad(fileAttribute, fileViewName);
        if (0 != response.getCode()) {
            model.addAttribute("msg", response.getMsg());
            model.addAttribute("fileType", fileAttribute.getSuffix());
            return "fileNotSupported";
        }
        fileAttribute.setFileRealName(fileAttribute.getName());
        fileAttribute.setFileViewName(fileViewName);
        // 清理历史转换数据
        asyncTaskBiz.updateUrlViewInfo(url, fileViewName);
        return filePreview.filePreviewHandle(model, fileAttribute);
    }

    /**
     * @author dehui dou
     * @description 压缩文件内部文件预览, 参数:fileKey，fileUniqueId
     * @param model
     * @param fileAttribute
     * @return java.lang.String
     */
    private String fileKeyView(Model model, FileAttribute fileAttribute) {
        String fileKey = fileAttribute.getFileKey();
        String suffix = fileKey.substring(fileKey.lastIndexOf(".") + 1);
        FileType fileType = FileUtils.typeFromFileFormat(suffix);
        FilePreview filePreview = FilePreviewFactory.get(fileType);
        if (filePreview == null) {
            model.addAttribute("msg", String.format("文件类型【%s】不支持", fileType));
            return "fileNotSupported";
        }
        String fileUniqueId = fileAttribute.getFileUniqueId();
        String fileName = fileUniqueId + File.separator + fileKey;
        fileAttribute.setFileViewName(fileName);
        fileAttribute.setFileRealName(fileKey);
        return FilePreviewFactory.getCompressInner().filePreviewHandle(model, fileAttribute);
    }

}
